<?
/**
 * VoiceOne Webservices Methods
 *  
 * @package voiceone_webservices
 * @subpackage rule
 */
//******************************************************************************
//******************           PUBLIC FUNCTIONS            *********************
//******************************************************************************
/********************************  RULESET  ***********************************/
/**
* FUNCTION: getRule
* Get ruleset structure
* @param id:int -> Id of the ruleset, all if empty or zero
* @param type:int -> type of ruleset (1 for RULE_OUTGOING or 2 for RULE_INCOMING)
* @return:RuleArray -> Array of structure contains rulset data
*/
function getRule($id,$type=""){
  global $db;
  $ret=array();
  //extract rulesets
  if($id!="") $condition=" WHERE id='".string2sql($id)."'";
  else if($type!="") $condition=" WHERE type='".string2sql($type)."'";
  $qry="SELECT * FROM cw_rule $condition";
  $res=$db->Execute($qry);
  if($res!==false){
    while($arr=$res->FetchRow()){
      //add ruleset's incoming/outgoing rule 
      $arr["outgoing"]=array();
      $arr["incoming"]=array();
      if($arr["type"]==RULE_OUTGOING){
        $qry="SELECT * FROM cw_rule_outgoing  WHERE rule='".string2sql($arr["id"])."' ORDER BY priority";
        $r=$db->Execute($qry);
        if($r!==false){
          while($a=$r->FetchRow()) {
            $arr["outgoing"][]=$a;
          }
        }
      }else if($arr["type"]==RULE_INCOMING){
        $qry="SELECT * FROM cw_rule_incoming  WHERE rule='".string2sql($arr["id"])."' ORDER BY priority";
        $r=$db->Execute($qry);
        if($r!==false){
          while($a=$r->FetchRow()){
            $a["from_number"]=split("\|",$a["from_number"]);
            $arr["incoming"][]=$a;
          }
        }
      }
      //add ruleset jump
      $arr["jump"]=array();
      $qry="SELECT * FROM cw_rule_jump WHERE ruleset_from='".string2sql($arr["id"])."'";
      $r=$db->Execute($qry);
      if(($r!==false)&&($a=$r->FetchRow())){
        //verify jump validity
        $qry="SELECT * FROM `cw_rule_jump` WHERE id='".string2sql($a["id"])."' AND NOW()<'".string2sql($a["end_of_life"])."'";
        $r=$db->Execute($qry);
        if($r!==false){
          $q=$r->RecordCount();
          if($q>0){ //jump is valid
            $arr["jump"]=$a;
          }else{   //jump is expired, delete it
            $qry="DELETE FROM `cw_rule_jump` WHERE ruleset_from='".$a["ruleset_from"]."'";
            $db->Execute($qry);
          }
        }
      }
      //add structure to return array
      $ret[]=$arr;
    }
  }
  //return
  return $ret;
}
/**
* FUNCTION: putRule
* Create/modify a ruleset
* @param rule:Rule -> ruleset data structure
* @return:int -> If success returns 1, else returns zero
*/
function putRule($rule){
  global $db;
  //delete ruleset if it already exists
  if(isset($rule["id"])){
    delRule($rule["id"],false);
    $idk="id,";
    $idv=$rule["id"].",";
  }
  //extract ruleset type
  if(is_array($rule["outgoing"])) $type=RULE_OUTGOING;
  else if (is_array($rule["incoming"])) $type=RULE_INCOMING;
  else $type=$rule["type"];
  //insert ruleset
  $qry="INSERT INTO cw_rule ($idk name,type,description) ";
  $qry.="VALUES ($idv '".string2sql($rule["name"])."','".string2sql($type)."','".string2sql($rule["description"])."')";
  $res=$db->Execute($qry);
  if($res===false) return 0;
  //return value
  if($rule["id"]=="") $ret=$db->Insert_Id();
  else $ret=$rule["id"];
  //set/delete jump
  if((is_array($rule["jump"]))&&($rule["jump"]["ruleset_to"]!=0)){
    $qry="INSERT INTO `cw_rule_jump`(`ruleset_from`,`ruleset_to`,`end_of_life`) ";
    $qry.="VALUES('".string2sql($ret)."','".string2sql($rule["jump"]["ruleset_to"])."','".string2sql($rule["jump"]["end_of_life"])."')";
    $res=$db->Execute($qry);
    if($res===false) return 0;
  }
  //write the ast_config
  if($type==RULE_OUTGOING){
    putAstConfig("extensions.conf", $rule["name"], "include", "_all_");
    //putAstConfig("extensions.conf", $rule["name"], "exten", "h,1,PlayTones(Congestion)");
    putAstConfig("extensions.conf", $rule["name"], "exten", "i,1,PlayTones(Congestion)");
    putAstConfig("extensions.conf", $rule["name"], "exten", "t,1,Hangup");
  }
  //return
  return $ret;
}
/**
* FUNCTION: delRule
* Delete a ruleset
* @param id:int -> id of the ruleset to delete
* @return:int -> If success returns 1, else returns zero
*/
function delRule($id,$delRules=true){
  global $db;
  //check input value
  if((trim($id)=="")||($id==0)) return 0;
  //get rule name
  $rulesetArr=getRule($id);
  if((!is_array($rulesetArr))||(!is_array($rulesetArr[0]))) return 0;
  $name=$rulesetArr[0]["name"];
  //delete rule
  $qry="DELETE FROM cw_rule WHERE id='".string2sql($id)."'";
  $res=$db->Execute($qry);
  if($res===false) return 0;
  //delete rulset's rules
  if($delRules===true){
    $qry="DELETE FROM cw_rule_outgoing WHERE rule='".string2sql($id)."'";
    $res=$db->Execute($qry);
    if($res===false) return 0;
    $qry="DELETE FROM cw_rule_incoming WHERE rule='".string2sql($id)."'";
    $res=$db->Execute($qry);
    if($res===false) return 0;
  }
  //delete ruleset jump
  $qry="DELETE FROM cw_rule_jump WHERE ruleset_from='".string2sql($id)."'";
  $res=$db->Execute($qry);
  if($res===false) return 0;
  //remove the entry from the ast_config
  if(trim($name)!=""){
    $res=delAstConfig("extensions.conf",$name,"%");
  }
  //return
  return 1;
}
/*****************************  OUTGOING RULE  ********************************/
/**
* FUNCTION: getOutgoingRule
* Get the outgoing rule
* @param id:int -> id of the outgoing rule, all if empty or zero
* @return:OutgoingRuleArray -> Array of structure of outgoing rule
*/
function getOutgoingRule($id) {
  global $db;
  $ret=array();
  //extract outgoing rule
  if($id!="") $condition=" WHERE id='".string2sql($id)."'";
  $qry="SELECT * FROM cw_rule_outgoing $condition ORDER BY priority ASC";
  $res=$db->Execute($qry);
  if($res!==false){
    while($arr=$res->FetchRow()){
      $ret[]=$arr;
    }
  }
  //return
  return $ret;
}
/**
* FUNCTION: putOutgoingRule
* Create/modify an outgoing rule
* @param rule:OutgoingRule -> Outgoing rule data structure
* @return:int -> If success returns 1, else returns zero
*/
function putOutgoingRule($rule) {
  global $db;
  //delete ruleset if it already exists
  if($rule["id"]!=""){
    delOutgoingRule($rule["id"]);
    $idk="`id`,";
    $idv=$rule["id"].",";
  } 
  //set variables
  $ruleId=intval($rule["rule"]);
  $priority=intval($rule["priority"]);
  $timesegment=intval($rule["timesegment"]);
  $group=intval($rule["group"]);
  $entity=intval($rule["entity"]);
  $resource=$rule["resource"];
  $provider=intval($rule["provider"]);
  $action=intval($rule["action"]);
  //get priority
  if ($priority==0) {
    $qry="SELECT MAX(priority) as max FROM cw_rule_outgoing WHERE rule=$ruleId";
    $res=$db->Execute($qry);
    $max=$res->FetchRow();
    $priority=intval($max["max"])+1;
  }
  //insert the rule
  $qry= "INSERT INTO cw_rule_outgoing ($idk `rule`,`priority`,`timesegment`,`group`,`entity`,`resource`,`provider`,`action`) ";
  $qry.="VALUES ($idv '".string2sql($ruleId)."','".string2sql($priority)."','".string2sql($timesegment)."','".string2sql($group)."',";
  $qry.="'".string2sql($entity)."','".string2sql($resource)."','".string2sql($provider)."','".string2sql($action)."')";
  $res=$db->Execute($qry);
  if($res===false) return 0;
  if($rule["id"]=="") $ret=$db->Insert_Id();
  else $ret=$rule["id"];
  //return
  return $ret;
}
/**
* FUNCTION: delOutgoingRule
* Delete an outgoing rule
* @param id:int -> id of the outgoing rule to delete
* @return:int -> If success returns 1, else returns zero
*/
function delOutgoingRule($id) {
  global $db;
  //check input value
  if((trim($id)=="")||($id==0)) return 0;
  //delete rule
  $qry="DELETE FROM cw_rule_outgoing WHERE id=$id";
  $res=$db->Execute($qry);
  if($res===false) return 0;
  //return
  return 1;
}
/*****************************  INCOMING RULE  ********************************/
/**
* FUNCTION: getIncomingRule
* Get the incoming rule
* @param id:int -> id of the incoming rule, all if empty or zero
* @return:IncomingRuleArray -> Array of structure of incoming rule
*/
function getIncomingRule($id){
  global $db;
  $ret=array();
  //extract incoming rule
  if($id!="") $condition=" WHERE id=$id ";
  $qry="SELECT * FROM cw_rule_incoming $condition ORDER BY priority ASC";
  $res=$db->Execute($qry);
  if($res!==false){
    while($arr=$res->FetchRow()){
      $arr["from_number"]=split("\|",$arr["from_number"]);
      $ret[]=$arr;
    }
  }
  //return
  return $ret;
}
/**
* FUNCTION: putIncomingRule
* Create/modify an incoming rule
* @param rule:IncomingRule -> Incoming rule data structure
* @return:int -> If success returns rule id, else returns zero
*/
function putIncomingRule($rule){
  global $db;
  //delete rule if it already exists
  if($rule["id"]!=""){
    delIncomingRule($rule["id"]);
    $idk="`id`,";
    $idv=$rule["id"].",";
  } 
  //set variables
  $ruleId=intval($rule["rule"]);
  $priority=intval($rule["priority"]);
  $timesegment=intval($rule["timesegment"]);
  $callertype=$rule["callertype"];
  $callerid=$rule["callerid"];
  $from_channel=intval($rule["from_channel"]);
  if($rule["from_number"]!="") $from_number=implode("|",$rule["from_number"]);
  $macro=intval($rule["macro"]);
  $parameter=$rule["parameter"];
  $duration=intval($rule["duration"]);
  //get priority
  if ($priority==0) {
    $qry="SELECT MAX(priority) as max FROM cw_rule_incoming WHERE rule=$ruleId";
    $res=$db->Execute($qry);
    $max=$res->FetchRow();
    $priority=intval($max["max"])+1;
  }
  //insert the rule  
  $qry="INSERT INTO cw_rule_incoming ($idk `rule`,`priority`,`timesegment`,`callertype`,`callerid`,`from_channel`,`from_number`,`macro`,`parameter`,`duration`) ";
  $qry.="VALUES ($idv $ruleId,'".string2sql($priority)."','".string2sql($timesegment)."','".string2sql($callertype)."','".string2sql($callerid)."','".string2sql($from_channel)."',";
  $qry.="'".string2sql($from_number)."','".string2sql($macro)."','".string2sql($parameter)."','".string2sql($duration)."')";
  $res=$db->Execute($qry);
  //return value
  if($rule["id"]=="") $ret=$db->Insert_Id();
  else $ret=$rule["id"];
  //return
  return $ret;
}
/**
* FUNCTION: delIncomingRule
* Delete an incoming rule
* @param id:int -> id of the incoming rule to delete
* @return:int -> If success returns 1, else returns zero
*/
function delIncomingRule($id) {
  global $db;
  //check input value
  if((trim($id)=="")||($id==0)) return 0;
  //delete rule
  $qry="DELETE FROM cw_rule_incoming WHERE id=$id";
  $res=$db->Execute($qry);
  if($res===false) return 0;
  //return
  return 1;
}
/**
* FUNCTION: moveRule
* change the incoming/outgoing rule priority in a ruleset
* @param id:int -> id of the rule to move
* @param direction:int -> direction af the movement (1 for up or 2 for down)
* @param type:int -> type of ruleset (1 for RULE_OUTGOING or 2 for RULE_INCOMING)
* @param top:int -> if 1 place the rule at the top/bottom of the ruleset depending on direction
* @return:int -> If success returns 1, else returns zero
*/
function moveRule($id,$direction,$type=RULE_OUTGOING,$top=0) {
  global $db;
  if ($type==RULE_OUTGOING) $table="cw_rule_outgoing";
  if ($type==RULE_INCOMING) $table="cw_rule_incoming";
  //get the rule set
  $qry="SELECT * FROM $table WHERE id=$id";
  $res=$db->Execute($qry);
  $arr=$res->FetchRow();
  $ruleSet=$arr["rule"];
  //if top!=0 calculate rounds
  if(($top==1)and($direction==1)){
    $qry="SELECT * FROM $table WHERE rule='".string2sql($ruleSet)."' AND id='".$id."' ORDER BY priority";
    $res=$db->Execute($qry);
    if($res!==false){
      while($arr=$res->FetchRow()){
        $prio=$arr["priority"];
      }
    }
		$qry="SELECT count(*) as rules_prev FROM $table WHERE rule='".string2sql($ruleSet)."' AND priority<".string2sql($prio)." ";
    $res=$db->Execute($qry);
    if($res!==false){
		  while($arr=$res->FetchRow()){
        $rounds=$arr["rules_prev"];
      }
    }
  }else if(($top==1)and($direction==-1)){
    $qry="SELECT * FROM $table WHERE rule=$ruleSet AND id=$id ORDER BY priority";
    $res=$db->Execute($qry);
    if($res!==false){
      while($arr=$res->FetchRow()){
        $prio=$arr["priority"];
      }
    }
		$qry="SELECT count(*) as rules_next FROM $table WHERE rule='".string2sql($ruleSet)."' AND priority>".string2sql($prio)." ";
    $res=$db->Execute($qry);
    if($res!==false){
  		while($arr=$res->FetchRow()){
        $rounds=$arr["rules_next"];
      }
    }
  }else $rounds=1;
  //move rules
  for($i=0;$i<$rounds;$i++){
    $repeat=true;
    $qry="SELECT * FROM $table WHERE rule='".string2sql($ruleSet)."' ORDER BY priority";
    $res=$db->Execute($qry);
    if($res!==false){
      while($repeat){
        $arr=$res->FetchRow();
        $nextId=$currentId;
        $currentId=$previousId;
        $previousId=$arr["id"];
        $nextPr=$currentPr;
        $currentPr=$previousPr;
        $previousPr=$arr["priority"];
        if($currentId==$id){
          if(($direction==1)||($direction=="1")){
            $db->Execute("UPDATE $table set priority=$nextPr    WHERE id=$id");      
            $db->Execute("UPDATE $table set priority=$currentPr WHERE id=$nextId");
          }else{
            $db->Execute("UPDATE $table set priority=$previousPr WHERE id=$id");
            $db->Execute("UPDATE $table set priority=$currentPr  WHERE id=$previousId");
          }      
        }
        if($arr===false) $repeat=false; 
      }
    }
  }
  //return
  return 1;
}
//******************************************************************************
//*****************           PRIVATE FUNCTIONS            *********************
//******************************************************************************
/**
* FUNCTION: extractRuleFromOption
* Extract ruleset from an array of technology options
* @param optionArr:AssociativeArray -> Array of technology options
* @param tech:int -> Technology constant
* @return:int -> id of matched ruleset
*/
function extractRuleFromOption($optionArr,$tech) {
  global $db;
  //get tech infos
  $techArr=getTechnology($tech);
  if((!is_array($techArr))||(!is_array($techArr[0]))) return 0;  
  $techName=$techArr[0]["name"];
  //change option structure
  if(!is_array($optionArr)) return 0;
  foreach($optionArr as $o){
    $optArr[$o["key"]]=$o["value"];
  }
  //extract ruleset name from technology
  $qry="SELECT * FROM cw_option o WHERE category='".string2sql($techName)."'";
  $res=$db->Execute($qry);
  while($arr=$res->FetchRow()){
    switch($tech){
      default:
        if(($arr["name"]=="context")&&(@array_key_exists($arr["id"],$optArr))) $ruleName=$optArr[$arr["id"]];
      break;
    }
  }
  //extract ruleset from name
  $ret=0;
  if($ruleName!=""){
    $qry="SELECT * FROM cw_rule WHERE name='".string2sql($ruleName)."'";
    $res=$db->Execute($qry);
    if($res!==false){
      if($arr=$res->FetchRow()){
        $ret=$arr["id"];
      }
    }
  }
  //return
  return $ret;
}
?>